`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2017/10/23 15:21:30
// Design Name: 
// Module Name: controller
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module controller(
	input wire clk,rst,
	//decode stage
	input wire[5:0] opD,functD,
	input wire[4:0] branchopD,
	output wire branchD,
	output wire signextendD,
	
	//execute stage
	input wire flushE,
	output wire memtoregE,alusrcE,
	output wire regdstE,regwriteE,	
	output wire[7:0] alucontrolE,
    output wire hiloselE,
    output wire reg_alu_selE,
    output wire[3:0] bran_selE,
    output wire jrselE,jalselE,jalrselE,
    input wire alustallE,
    
	//mem stage
	output wire memtoregM,memwriteM,regwriteM,
	output wire[1:0] hilowriteM,
	output wire jumpM,
	input wire bran_takeM,
	output wire pcsrcM,
	input wire alustallM,
				
	//write back stage
	output wire memtoregW,regwriteW,
	output wire hilo_regW,
	output wire[1:0] hilowriteW,
	input wire alustallW
    );
	
	//decode stage
	wire[5:0] aluopD;
	wire memtoregD,memwriteD,alusrcD,
		regdstD,regwriteD;
	wire hiloselD,hilo_regD;
	wire[1:0] hilowriteD;
	wire[7:0] alucontrolD;
    wire alu_unsignD,reg_alu_selD;
    wire[3:0] bran_selD;
    wire jrselD,jalselD,jalrselD;
    
	//execute stage
	wire memwriteE;
	wire hilo_regE;
	wire[1:0] hilowriteE;
	wire branchE,jumpE;
    
    //mem stage
    wire hilo_regM;
    
	maindec md(
		opD,
		functD,
		branchopD,
		memtoregD,memwriteD,
		branchD,alusrcD,
		regdstD,regwriteD,
		jumpD,
		signextendD,
		hiloselD,
		hilo_regD,
		hilowriteD,
		reg_alu_selD,
		bran_selD,
		jrselD,
		jalselD,
		jalrselD,
		alucontrolD
		);

//	assign pcsrcD = branchD & equalD;

	//pipeline registers
	flopenrc #(28) regE(
		clk,
		rst,
		~alustallE,
		flushE,
		{memtoregD,memwriteD,alusrcD,regdstD,regwriteD,hiloselD,hilo_regD,hilowriteD,alucontrolD,alu_unsignD,reg_alu_selD,bran_selD,jrselD,jalselD,jalrselD,branchD,jumpD},
		{memtoregE,memwriteE,alusrcE,regdstE,regwriteE,hiloselE,hilo_regE,hilowriteE,alucontrolE,alu_unsignE,reg_alu_selE,bran_selE,jrselE,jalselE,jalrselE,branchE,jumpE}
		);
		
	flopenr #(8) regM(
		clk,rst,~alustallM,
		{memtoregE,memwriteE,regwriteE,hilo_regE,hilowriteE,branchE,jumpE},
		{memtoregM,memwriteM,regwriteM,hilo_regM,hilowriteM,branchM,jumpM}
		);
	assign pcsrcM = bran_takeM & branchM;
	
	flopenr #(5) regW(
		clk,rst,~alustallW,
		{memtoregM,regwriteM,hilo_regM,hilowriteM},
		{memtoregW,regwriteW,hilo_regW,hilowriteW}
		);
endmodule
